/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package sk.vasicek.drinkmanager.activity;

import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import sk.vasicek.drinkmanager.R;
import sk.vasicek.drinkmanager.domain.DrinkPoint;
import sk.vasicek.drinkmanager.domain.Language;
import sk.vasicek.drinkmanager.service.BackgroundAdapter;
import sk.vasicek.drinkmanager.service.DrinkPlaceHelper;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.RatingBar;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.UiSettings;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.GroundOverlay;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.maps.OverlayItem;

public class MapsOverlayActivity extends android.support.v4.app.FragmentActivity implements OnMarkerClickListener, OnInfoWindowClickListener, OnMarkerDragListener, LocationListener {

	// custom overlays
	private static final LatLng bratislavaLoc = new LatLng(48.152, 17.176);
	private static final LatLng avionLoc = new LatLng(48.166443, 17.181373);
	private static final LatLng auparkLoc = new LatLng(48.133144, 17.108309);
	private static final String TAG = MapsOverlayActivity.class.getSimpleName();

	// maps init
	private GoogleMap mMap;
	private GroundOverlay mGroundOverlay1;
	private GroundOverlay mGroundOverlay2;
	private DrinkPlaceHelper drinkDatabaseHelper;
	private ImageButton saveMyPosition;
	private SharedPreferences prefs;
	private LocationManager locationManager;

	// on long press
	private int minMillisecondThresholdForLongClick = 300;
	private long startTimeForLongClick = 0;
	private float xScreenCoordinateForLongClick;
	private float yScreenCoordinateForLongClick;
	private float xtolerance = 10;
	private float ytolerance = 10;
	private float xlow;
	private float xhigh;
	private float ylow;
	private float yhigh;

	// location for new item
	protected LatLng loc;
	private double lat;
	private double longitude;

	// add new item dialog
	protected Dialog dialog;
	protected TextView eventName;
	protected TextView eventDescription;
	protected TextView ratingLabel;
	protected RatingBar eventRating;
	protected Button updateButton;
	protected Button removeButton;
	private boolean isDragged;

	// on item click dialog
	private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
	private Context mContext;
	private DrinkPlaceHelper eventDatabaseHelper;
	private DrinkPoint eventPoint;
	private TextView name;
	private TextView description;
	private TextView ratingDialogLabel;
	private RatingBar eventDialogRating;
	private Button updateDialogButton;
	private Button removeDialogButton;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.map_with_overlay);
		Configuration config = getBaseContext().getResources().getConfiguration();
		Locale locale = Language.getApplicationLanguage(this);
		Locale.setDefault(locale);
		config.locale = locale;
		getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
		setUpMapIfNeeded();
		prefs = PreferenceManager.getDefaultSharedPreferences(this);
		BackgroundAdapter.updateBackgroundFromPrefs(prefs, this);

		int styleId = Integer.parseInt(prefs.getString("BackgroundPref", "0"));
		Drawable myCharSign = this.getResources().getDrawable(BackgroundAdapter.getStyle(styleId).getCharIcon());

		Drawable myPoiSign = this.getResources().getDrawable(BackgroundAdapter.getStyle(styleId).getPoiIcon());

		this.saveMyPosition = (ImageButton) this.findViewById(R.id.saveMyPosition);
		this.saveMyPosition.setImageDrawable(myPoiSign);
		this.saveMyPosition.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Location location = mMap.getMyLocation();
				if (location != null) {
					Date timeOfLocation = new Date(location.getTime());
					drinkDatabaseHelper.insertDrinkMapPoint(
							getResources().getText(R.string.myPosition) + "",
							getResources().getText(R.string.myPosition) + ": " + String.valueOf(location.getLatitude()).subSequence(0, 6) + " "
									+ String.valueOf(location.getLongitude()).subSequence(0, 6) + " " + timeOfLocation.getDate() + "." + timeOfLocation.getMonth() + ". " + timeOfLocation.getHours()
									+ ":" + timeOfLocation.getMinutes() + ":" + timeOfLocation.getSeconds(), 0.0d, location.getLatitude(), location.getLongitude());
//					new WifiScannerService(MapsOverlayActivity.this, new LatLng(location.getLatitude(), location.getLongitude()));
					addMarkersToMap();
					mMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(), location.getLongitude())));
				}
				// Toast.makeText(DrinkMapsActivity.this.getApplicationContext(),
				// getResources().getText(R.string.pointSaved),
				// Toast.LENGTH_SHORT).show();
			}
		});

		mMap.setOnMarkerClickListener(this);
		mMap.setOnInfoWindowClickListener(this);
		mMap.setOnMarkerDragListener(this);
	}

	@Override
	protected void onResume() {
		super.onResume();
		setUpMapIfNeeded();
	}

	private void setUpMapIfNeeded() {
		if (mMap == null) {
			mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
			if (mMap != null) {
				setUpMap();
			}
		}
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		if (isDragged)
			return super.dispatchTouchEvent(ev);
		int actionType = ev.getAction();
		drinkDatabaseHelper = new DrinkPlaceHelper(MapsOverlayActivity.this.getApplicationContext());

		if (actionType == MotionEvent.ACTION_DOWN) {
			startTimeForLongClick = ev.getEventTime();
			xScreenCoordinateForLongClick = ev.getX();
			yScreenCoordinateForLongClick = ev.getY();

		} else if (actionType == MotionEvent.ACTION_MOVE) {
			if (ev.getPointerCount() > 1) {
				startTimeForLongClick = 0;
			} else {
				float xmove = ev.getX();
				float ymove = ev.getY();
				xlow = xScreenCoordinateForLongClick - xtolerance;
				xhigh = xScreenCoordinateForLongClick + xtolerance;
				ylow = yScreenCoordinateForLongClick - ytolerance;
				yhigh = yScreenCoordinateForLongClick + ytolerance;
				if ((xmove < xlow || xmove > xhigh) || (ymove < ylow || ymove > yhigh)) {
					startTimeForLongClick = 0;
				}
			}

		} else if (actionType == MotionEvent.ACTION_UP) {
			long eventTime = ev.getEventTime();
			long downTime = ev.getDownTime();

			if (startTimeForLongClick == downTime) {
				if ((eventTime - startTimeForLongClick) > minMillisecondThresholdForLongClick) {
					float xup = ev.getX();
					float yup = ev.getY();
					xlow = xScreenCoordinateForLongClick - xtolerance;
					xhigh = xScreenCoordinateForLongClick + xtolerance;
					ylow = yScreenCoordinateForLongClick - ytolerance;
					yhigh = yScreenCoordinateForLongClick + ytolerance;
					if ((xup > xlow && xup < xhigh) && (yup > ylow && yup < yhigh)) {

						long totaltime = eventTime - startTimeForLongClick;
						String strtotaltime = Long.toString(totaltime);
						Log.d("long press detected: ", strtotaltime);

						com.google.android.gms.maps.Projection proj = mMap.getProjection();
						loc = proj.fromScreenLocation(new Point((int) (ev.getX(ev.getPointerCount() - 1)), (int) (ev.getY(ev.getPointerCount() - 1))));
						lat = loc.latitude;
						longitude = loc.longitude;

						dialog = new Dialog(MapsOverlayActivity.this);

						dialog.setContentView(R.layout.drink_detail);
						dialog.setTitle(getResources().getText(R.string.myPosition));
						dialog.setCancelable(true);
						eventName = (TextView) dialog.findViewById(R.id.title);
						eventDescription = (TextView) dialog.findViewById(R.id.snippet);
						ratingLabel = (TextView) dialog.findViewById(R.id.ratingLabel);
						eventRating = (RatingBar) dialog.findViewById(R.id.placeRating);

						updateButton = (Button) dialog.findViewById(R.id.updateButton);
						removeButton = (Button) dialog.findViewById(R.id.removeButton);

						ratingLabel.setVisibility(View.GONE);
						eventRating.setVisibility(View.GONE);
						removeButton.setVisibility(View.GONE);

						updateButton.setOnClickListener(new OnClickListener() {

							@Override
							public void onClick(View v) {
								boolean dateOk = true;

								String name = eventName.getText().toString();
								String description = eventDescription.getText().toString();

								if (dateOk) {
									double rating = (double) 0d;// placeRating.getRating();
									drinkDatabaseHelper.insertDrinkMapPoint(name + "", description + "", rating, lat, longitude);
//									new WifiScannerService(MapsOverlayActivity.this, new LatLng(lat, longitude));
									addMarkersToMap();
									mMap.animateCamera(CameraUpdateFactory.newLatLng(loc));
									Toast.makeText(MapsOverlayActivity.this.getApplicationContext(), getResources().getText(R.string.placeInfoUpdatedToast), Toast.LENGTH_SHORT).show();
									dialog.dismiss();
								}
							}
						});
						dialog.show();
					}
				}
			}
		}
		return super.dispatchTouchEvent(ev);
	}

	@Override
	public boolean onMarkerClick(final Marker marker) {
		mContext = this;
		Marker item = marker;
		final Dialog mainDialog = new Dialog(mContext);

		mainDialog.setContentView(R.layout.drink_detail);
		mainDialog.setTitle(getResources().getString(R.string.updatePlaceInfo));
		mainDialog.setCancelable(true);

		eventDatabaseHelper = new DrinkPlaceHelper(this);

		if (item.getTitle() != null && !"".equals(item.getTitle())) {
			eventPoint = eventDatabaseHelper.getDrinkMapPointByID(Integer.parseInt(item.getTitle().trim()));
		}

		name = (TextView) mainDialog.findViewById(R.id.title);
		description = (TextView) mainDialog.findViewById(R.id.snippet);
		ratingDialogLabel = (TextView) mainDialog.findViewById(R.id.ratingLabel);
		eventDialogRating = (RatingBar) mainDialog.findViewById(R.id.placeRating);
		if (eventPoint != null) {
			name.setText(eventPoint.getTitle());
			description.setText(eventPoint.getSnippet());
			eventDialogRating.setRating((float) eventPoint.getRating());
		}
		updateDialogButton = (Button) mainDialog.findViewById(R.id.updateButton);
		removeDialogButton = (Button) mainDialog.findViewById(R.id.removeButton);

		updateDialogButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				boolean dateOk = true;
				if (eventPoint != null) {
					String name = MapsOverlayActivity.this.name.getText().toString();
					if (dateOk) {
						String description = MapsOverlayActivity.this.description.getText().toString();
						double rating = (double) eventDialogRating.getRating();
						eventDatabaseHelper.updateDrinkMapPoint(eventPoint.getId(), name + "", description + "", rating);
						Toast.makeText(mContext, mContext.getResources().getText(R.string.placeInfoUpdatedToast), Toast.LENGTH_SHORT).show();
					}
				}
				if (dateOk)
					mainDialog.dismiss();
			}
		});

		removeDialogButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
				builder.setMessage(getResources().getText(R.string.placeRemovePrompt)).setCancelable(true)
						.setPositiveButton(getResources().getText(R.string.yesAnswer), new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {
								if (eventPoint != null) {
									eventDatabaseHelper.removeDrinkMapPoint(eventPoint);
									Toast.makeText(mContext, mContext.getResources().getText(R.string.placeRemoveToast), Toast.LENGTH_SHORT).show();
									addMarkersToMap();
									dialog.dismiss();
									mainDialog.dismiss();
								}
							}
						}).setNegativeButton(mContext.getResources().getText(R.string.noAnswer), new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {
								dialog.cancel();
							}
						});
				AlertDialog alert = builder.create();
				alert.show();

			}
		});

		mainDialog.show();
		return true;
	}

	@Override
	public void onInfoWindowClick(Marker marker) {
	}

	@Override
	public void onMarkerDragStart(Marker marker) {
		Toast.makeText(MapsOverlayActivity.this, "Drag place to desired location", Toast.LENGTH_SHORT).show();
		isDragged = true;
	}

	@Override
	public void onMarkerDragEnd(Marker marker) {
		eventDatabaseHelper = new DrinkPlaceHelper(this);
		eventDatabaseHelper.updateDrinkMapPointLocation(Integer.parseInt(marker.getTitle().trim()), marker.getPosition().latitude, marker.getPosition().longitude);
		Handler handler = new Handler();
		handler.postDelayed(new Runnable() {

			@Override
			public void run() {
				isDragged = false;
			}
		}, 0);
	}

	@Override
	public void onMarkerDrag(Marker marker) {
		isDragged = true;
	}

	private void setUpMap() {
		mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(bratislavaLoc, 12));
		mMap.setMyLocationEnabled(true);
		mMap.setIndoorEnabled(true);
		// mMap.setTrafficEnabled(true);

		UiSettings mUiSettings = mMap.getUiSettings();
		mUiSettings.setZoomControlsEnabled(true);
		mUiSettings.setCompassEnabled(true);
		mUiSettings.setMyLocationButtonEnabled(true);
		mUiSettings.setScrollGesturesEnabled(true);
		mUiSettings.setZoomGesturesEnabled(true);
		mUiSettings.setTiltGesturesEnabled(true);
		mUiSettings.setRotateGesturesEnabled(true);
		addMarkersToMap();
//		mGroundOverlay1 = mMap.addGroundOverlay(new GroundOverlayOptions().image(BitmapDescriptorFactory.fromResource(R.drawable.aupark_ba_clear_rotated)).anchor(0.5f, 0.5f)
//				.position(auparkLoc, 450f, 261f));
//		mGroundOverlay2 = mMap.addGroundOverlay(new GroundOverlayOptions().image(BitmapDescriptorFactory.fromResource(R.drawable.avion_ba_clear_rotated)).anchor(0.5f, 0.5f)
//				.position(avionLoc, 490f, 750f));
	}

	private void addMarkersToMap() {
		mMap.clear();

		drinkDatabaseHelper = new DrinkPlaceHelper(getApplicationContext());
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
		int backgroundId = Integer.parseInt(prefs.getString("BackgroundPref", "0"));

		ArrayList<DrinkPoint> drinkPoints = new ArrayList<DrinkPoint>();
		try {
			drinkPoints = drinkDatabaseHelper.getAllDrinkPoints();
		} catch (Exception ex) {
			Log.e(TAG, "Failed to read drink points", ex);
		}
		if (drinkPoints != null && drinkPoints.size() > 0) {
			for (DrinkPoint point : drinkPoints) {
				Marker marker = mMap.addMarker(new MarkerOptions().draggable(true).position(new LatLng(point.getLatitude(), point.getLongitude())).title(String.valueOf(point.getId()))
						.snippet(point.getSnippet()).icon(BitmapDescriptorFactory.fromResource(BackgroundAdapter.getStyle(backgroundId).getPoiIcon())));
				Log.d(TAG, "Adding point " + marker.getId() + " " + marker.getTitle() + " " + marker.getSnippet());
			}
		} else {
			Log.d(TAG, "There are no points");
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = this.getMenuInflater();
		inflater.inflate(R.menu.optionmenu, menu);
		MenuItem settings = menu.findItem(R.id.settings);
		settings.setIntent(new Intent(this, SettingsActivity.class));
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case R.id.exit:
			MapsOverlayActivity.this.finish();
			return true;
		case R.id.settings:
			Intent settingsIntent = item.getIntent();
			this.startActivityForResult(settingsIntent, 0);
			return true;
		case android.R.id.home:
			// Toast.makeText(DrinkManagerListActivity.this.getApplicationContext(),
			// getResources().getText(R.string.alreadyToast),
			// Toast.LENGTH_SHORT).show();
			Intent intent = new Intent(this, DrinkManagerListActivity.class);
			intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			startActivity(intent);
			return true;
		case R.id.drinks:
			Intent drinksIntent = new Intent(getApplicationContext(), DrinkManagerListActivity.class);
			this.startActivityForResult(drinksIntent, 0);
			return true;
		case R.id.places:
			Intent placesIntent = new Intent(getApplicationContext(), DrinkPlacesActivity.class);
			this.startActivityForResult(placesIntent, 0);
			return true;
		case R.id.custom:
			Intent customIntent = new Intent(this, CustomDrinksActivity.class);
			this.startActivityForResult(customIntent, 0);
			// Toast.makeText(getApplicationContext(),
			// getResources().getText(R.string.alreadyToast),
			// Toast.LENGTH_SHORT).show();
			return true;
		case R.id.history:
			Intent historyIntent = new Intent(this, DrinkHistoryActivity.class);
			this.startActivityForResult(historyIntent, 0);
			// Toast.makeText(getApplicationContext(),
			// getResources().getText(R.string.alreadyToast),
			// Toast.LENGTH_SHORT).show();
			return true;
		case R.id.graphs:
			Intent graphsIntent = new Intent(this, DrinkGraphActivity.class);
			this.startActivityForResult(graphsIntent, 0);
			// Toast.makeText(getApplicationContext(),
			// getResources().getText(R.string.alreadyToast),
			// Toast.LENGTH_SHORT).show();
			return true;
		case R.id.back:
			Intent backIntent = new Intent(getApplicationContext(), BackgroundChooserActivity.class);
			this.startActivityForResult(backIntent, 0);
			return true;
		case R.id.map:
			// Intent mapsIntent = new Intent(getApplicationContext(),
			// DrinkMapsActivity.class);
			// this.startActivityForResult(mapsIntent, 0);
			Toast.makeText(MapsOverlayActivity.this.getApplicationContext(), getResources().getText(R.string.alreadyToast), Toast.LENGTH_SHORT).show();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	@Override
	public void onLocationChanged(Location arg0) {
	}

	@Override
	public void onProviderDisabled(String arg0) {
	}

	@Override
	public void onProviderEnabled(String arg0) {
	}

	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
	}
}
